package com.subfg.common.util.redis;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.BoundListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class RedisUtil<T> {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private ValueOperations<String, Object> valueOperations;

    /**  默认过期时长，单位：秒 */
    public final static long DEFAULT_EXPIRE = 60 * 60 * 24 * 7;
    /**  不设置过期时长 */
    public final static long NOT_EXPIRE = -1;
    private final static JSONObject jsonObject = new JSONObject() ;

    public void set(String key, Object value, long expire){
        valueOperations.set(key, value);
        if(expire != NOT_EXPIRE){
            redisTemplate.expire(key, expire, TimeUnit.SECONDS);
        }
    }

    public void set(String key, Object value){
        set(key, value, DEFAULT_EXPIRE);
    }

    /** 获取缓存的有效时间  **/
    public Long getExpireTime(String key) {
        return redisTemplate.getExpire(key);
    }

    public <T> T get(String key, Class<T> clazz, long expire) {
        String value = (String) valueOperations.get(key);
        if(expire != NOT_EXPIRE){
            redisTemplate.expire(key, expire, TimeUnit.SECONDS);
        }
        return value == null ? null : fromJson(value, clazz);
    }

    public Integer getInteger(String key) {
        return (Integer) valueOperations.get(key);
    }


    public <T> T get(String key, Class<T> clazz) {
        return get(key, clazz, NOT_EXPIRE);
    }

    public String get(String key, long expire) {
        String value = (String) valueOperations.get(key);
        if(expire != NOT_EXPIRE){
            redisTemplate.expire(key, expire, TimeUnit.SECONDS);
        }
        return value;
    }

    public Long addParam(String key, Long step){
        return redisTemplate.boundValueOps(key).increment(step);
    }


    public String get(String key) {
        return get(key, NOT_EXPIRE);
    }


    public void delete(String key) {
        redisTemplate.delete(key);
    }

    /**
     * Object转成JSON数据
     */
    private String toJson(Object object){
        if(object instanceof Integer || object instanceof Long || object instanceof Float ||
                object instanceof Double || object instanceof Boolean || object instanceof String){
            return String.valueOf(object);
        }
        return jsonObject.toJSONString(object);
    }



    /**
     * JSON数据，转成Object
     */
    private <T> T fromJson(String json, Class<T> clazz){
        return JSON.parseObject(json, clazz);
    }

    public boolean exists(String token) {
        String getToken = get(token);
        return getToken==null?false:true;
    }

    public void setExpireTime(String token) {
    }

    public BoundHashOperations boundHashOps(String key){
        return redisTemplate.boundHashOps(key);
    }

    /**
     *  数据存储格式为hash, 需自己构建bound
     * @param data
     */
    public void setBound(String redisKey, String keyValue, Object data) {
        BoundHashOperations boundHashOperations = boundHashOps(redisKey);
        boundHashOperations.put(keyValue, data);

    }

    /**
     * 取出 Redis 中的Map数据格式, 所有的包括键值对
     * @param redisKey
     * @return
     */
    public <T>T getAllBoundHashOps(String redisKey, Class<?> clazz) {
        Map map = redisTemplate.boundHashOps(redisKey).entries();
        return (T) new ObjectMapper().convertValue(map, clazz);
    }

    /**
     *  数据存储格式为hash, 不需自己构建bound
     * @param data
     */
    public void setBound(String keyValue, BoundHashOperations bound, Object data) {
        bound.put(keyValue, data);
    }

    public <T>T getBound(String redisKey, String keyValue, Class<T> clazz) {
        BoundHashOperations  bound = boundHashOps(redisKey);
        return (T) new ObjectMapper().convertValue(bound.get(keyValue), clazz);
    }

    public <T>T getBound(String keyValue, BoundHashOperations bound, Class<T> clazz) {
        StringBuilder sb = new StringBuilder("{\"joinList\":"+JSON.toJSONString(bound.get(keyValue))+"}");
        return (T) JSON.parseArray(JSON.parseObject(sb.toString()).getString("joinList"), clazz);
    }

    /** redis 存储list 数据格式 **/
    public void setRedisList(String redistKey, List data) {
        for (Object index : data) {
            redisTemplate.boundListOps(redistKey).rightPush(index);
        }
    }

    /** redis 存储list 数据格式 **/
    public void setRedisList(String redistKey, List data, long expire) {
        for (Object index : data) {
            redisTemplate.boundListOps(redistKey).rightPush(index);
        }
        if(expire != NOT_EXPIRE){
            redisTemplate.expire(redistKey, expire, TimeUnit.SECONDS);
        }
    }
    /** 从redis 中取出所有list 数据 **/
    public <T>T getRedisListAll(String redisKey) {
        BoundListOperations listKey = redisTemplate.boundListOps(redisKey);
        Long length = listKey.size();
        return (T) redisTemplate.boundListOps(redisKey).range(0, length);
    }
    /** 从redis 取出指定下标list 数据 **/
    public <T>T getRedisListIndex(String redisKey, Integer index) {
        return (T) redisTemplate.boundListOps(redisKey).index(index);
    }
}
